#ifndef TRACKBALL_H
#define TRACKBALL_H

#include <cmath>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include "common.h"

#define TRACKBALL_SENSITIVITY 50.0f

class Trackball {
    private:
        // Width and height of the screen
        int resW, resH;
        
        // Square of the radius of the trackball
        float rSq;
        
        // The view matrix
        glm::mat4 view;
        
        bool dragging;
        glm::vec3 dragStart;
        glm::vec3 dragStop;
        
/*============================================================================
We're going to assume that the viewer is looking down the negative z axis; at
the origin is a sphere which represents the trackball. We're going to
transform screen-space 2D vectors into this trackball-space. The only
thing we actually need to calculate is the z-coordinate (due to our setup).

Of course, there's a problem with this - sometimes, a screen space coordinate
will not map to a point on the sphere (as is the case if you click outside the
sphere). To take care of this, we use a piecewise function, with one part
being the sphere, and the other being a hyperbolic sheet. This piecewise
function looks something like a tablecloth draped over a tennis ball.

This allows us to map all screen space coordinates to a trackball space
coordinate.

See:
http://www.opengl.org/wiki/Trackball
============================================================================*/
        
    public:
        Trackball(int resW, int resH, float radius, glm::mat4 initialView) : 
            resW(resW), resH(resH), rSq(radius * radius),
            view(initialView), dragging(false) { }
        
        glm::vec3 ToTrackballCoords(int i, int j);
        glm::mat4 GetViewMatrix(bool debug) const;
        
        void MouseUpdate(bool mouseDown, int i, int j);
        void ScreenResize(int resW, int resH) { 
            this->resW = resW; 
            this->resH = resH;
        }
};

#endif